using System;
using System.Collections.Generic;
using System.Text;

namespace ImagesMath
{
    // Homogeneous matrices representing the transform and its inverse.
    //
    //   |       |   |           |        |      |
    //   |   L   | T |           |  invL  | invT |
    //   |       |   |           |        |      |
    //   |-------+---|           |--------+------|
    //   | 0 0 0 | 1 |           | 0 0 0  |   1  |
    public class Transformation
    {

        public Transformation()
        {
            M33 L = new M33();
            VR3 T = new VR3(0,0,0);
            this.L = L;
            this.invL = L.inverse();


            this.T = T;
            this.invT = -(invL * T);
        }

        public Transformation(M33 m)
        {
            
            VR3 T = new VR3(0, 0, 0);
            this.L = m;
            this.invL = m.inverse();


            this.T = T;
            this.invT = -(invL * T);
        }

        public Transformation(M33 L, VR3 T)
        {

            this.L = L;
            this.invL = L.inverse();
            

            this.T = T;
            this.invT = -(invL * T);

        }
        public Transformation(M33 L, VR3 T, M33 invL, VR3 invT)
        {
            this.l = L;
            this.invL = invL;
            this.t = T;
            this.invT = invT;
        }

        #region Accessors

        public M33 L
        {
            get { return this.l; }
            set {this.l = value; }
        }
        public M33 InvL
        {
            get { return this.invL; }
            set { this.invL = value; }
        }

        public VR3 T
        {
            get { return this.t; }
            set {this.t = value; }
        }
        public VR3 InvT
        {
            get { return this.invT; }
            set { this.invT = value; }
        }


        #endregion

        #region Functions

        /// Compute the concatenation of (*this) and Tr [ (*this)*Tr ]
          public virtual Transformation rightMultiply(Transformation Tr) 
          {
              M33 m1 = L * Tr.L ;
              VR3 v0 = L * Tr.T;
              VR3 v1 = T + v0;
              M33 m2 = Tr.invL * invL;
              VR3 v2 = Tr.invT + Tr.invL * invT;
              return new Transformation(m1, v1,m2 , v2);
          }
        /// Compute the concatenation of Tr and (*this) [ Tr*(*this) ]
        public virtual Transformation leftMultiply(Transformation Tr)              
          {
              return new Transformation(Tr.L*L, Tr.T+Tr.L*T, invL*Tr.invL, invT+invL*Tr.invT);
          }
        public virtual PR3 transform(PR3 p)               
          {
              return L * p + T;
          }
        public virtual PR3 invTransform(PR3 p)               
          {
              PR3 p1 = invL * p;
              VR3 v1 = new VR3(p1);
              VR3 v2 = v1 + invT;
              PR3 p2 = new PR3(v2);
              return p2;
              //return invL * p + invT;
          }
        public virtual VR3 transform(VR3 v) 
          {
              return L * v;
          }
        public virtual VR3 invTransform(VR3 v)
          {
              return invL * v;
          }

        #endregion

        protected M33 l, invL;
        protected VR3 t, invT;
    }
}

//#ifndef __mCG_TRANSFORM__
//#define __mCG_TRANSFORM__

//#include "mCGexception.h"
//#include "mCGalgebra.h"

//namespace mCG
//{

//  class Transform
//  {
//    public:

//// Homogeneous matrices representing the transform and its inverse.
////
////   |       |   |           |        |      |
////   |   L   | T |           |  invL  | invT |
////   |       |   |           |        |      |
////   |-------+---|           |--------+------|
////   | 0 0 0 | 1 |           | 0 0 0  |   1  |

//      m33 L, invL;
//      vR3 T, invT;

///// Constructors
//      Transform(const m33& __L=m33(),const vR3& __T=vR3());
//      Transform(const m33& __L,const vR3& __T,const m33& _invL,const vR3& _invT);

///// Compute the concatenation of (*this) and Tr [ (*this)*Tr ]
//      virtual Transform rightMultiply(const Transform& Tr) const;
///// Compute the concatenation of Tr and (*this) [ Tr*(*this) ]
//      virtual Transform leftMultiply (const Transform& Tr) const;
//      virtual pR3       transform    (const pR3& p) const;
//      virtual pR3       invTransform (const pR3& p) const;
//      virtual vR3       transform    (const vR3& v) const;
//      virtual vR3       invTransform (const vR3& v) const;
//  };







//}                                                 // namespace mCG
//#endif                                            // __mCG_TRANSFORM__

//
// Transform interface
//

//Transform::Transform(const m33& __L,const vR3& __T)
//:L(__L),invL(__L.inverse()),T(__T) { invT=-(invL*T); }

//Transform::Transform(const m33& __L,const vR3& __T,const m33& _invL,const vR3& _invT)
//:L(__L),invL(_invL),T(__T),invT(_invT) {}

//Transform Transform::rightMultiply(const Transform& Tr) const
//{
//  return Transform(L*Tr.L, T+L*Tr.T, Tr.invL*invL, Tr.invT+Tr.invL*invT);
//}


//Transform Transform::leftMultiply(const Transform& Tr) const
//{
//  return Transform(Tr.L*L, Tr.T+Tr.L*T, invL*Tr.invL, invT+invL*Tr.invT);
//}


//pR3 Transform::transform(const pR3& p) const
//{
//  return L*p+T;
//}


//pR3 Transform::invTransform(const pR3& p) const
//{
//  return invL*p+invT;
//}


//vR3 Transform::transform(const vR3& v) const
//{
//  return L*v;
//}


//vR3 Transform::invTransform(const vR3& v) const
//{
//  return invL*v;
//}

